"""
Case Type   : 资源池化系统视图
Case Name   : 开启按需回放+实时构建，执行switchover操作，查看系统视图gs_thread_memory_context
Create At   : 2025/2
Owner       : haomeng
Description :
    1、开启按需回放和实时构建特性
    2、主备节点查看系统表gs_thread_memory_context中DMSMemContext字段是否存在
    3、主备节点查看系统表gs_session_memory_detail中DMSMemContext字段是否存在
    4、查看enable_thread_pool参数
    5、mv掉dn目录，kill掉dn进程,查看集群状态
    6、新主节点查询相同系统视图gs_thread_memory_context中DMSMemContext字段是否存在
    7、新备节点查询相同系统视图gs_session_memory_detail中DMSMemContext字段是否存在
    8、恢复初始环境
Expect      :
    1、设置成功
    2、存在DMSMemContext字段及相关信息
    3、存在DMSMemContext字段及相关信息
    4、默认值为off
    5、原主异常，集群内产生新主
    6、存在DMSMemContext字段及相关信息
    7、存在DMSMemContext字段及相关信息
    8、环境恢复成功
History     :
"""

import os
import re
import time
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class ShareStorageSystemView(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.user_node = [CommonSH('PrimaryDbUser'), CommonSH('Standby1DbUser'), CommonSH('Standby2DbUser')]
        self.pri_user = Node(node='PrimaryDbUser')
        self.com = Common('PrimaryDbUser')
        self.constant = Constant()

        self.thread_pool = 'enable_thread_pool'
        self.param1 = 'recovery_parse_workers'
        self.param2 = 'recovery_redo_workers'
        self.param3 = 'ss_enable_ondemand_recovery'
        self.param4 = 'ss_ondemand_recovery_mem_size'
        self.param5 = 'ss_enable_ondemand_realtime_build'

        self.sys_view1 = 'gs_thread_memory_context'
        self.sys_view2 = 'gs_session_memory_detail'
        self.sys_view3 = 'gs_get_thread_memctx_detail'

    def test_ss_system_view(self):
        text = '-----step1:开启按需回放和实时构建特性  expect:设置成功-----'
        self.log.info(text)

        self.param_list = [self.param1, self.param2, self.param3, self.param4, self.param5]
        value_list = ['4', '4', 'on', '5GB', 'on']

        self.default_value = []
        for param in self.param_list:
            value = self.user_node[0].execut_db_sql(f'show {param}')
            self.default_value.append(value.splitlines()[-2].strip())
        self.log.info(self.default_value)

        for param in self.param_list:
            set_param = self.user_node[0].execute_gsguc('set',
                                                        self.constant.GSGUC_SUCCESS_MSG,
                                                        f'{param} = {value_list[self.param_list.index(param)]}')
            self.log.info(set_param)
            self.assertTrue(set_param, '参数设置失败')

        self.log.info('---重启集群使参数生效---')
        restart = self.user_node[0].restart_db_cluster(False)
        self.log.info(restart)
        self.assertTrue(restart)

        self.log.info('---查看参数值修改是否成功---')
        for param in self.param_list:
            value = self.user_node[0].execut_db_sql(f'show {param};')
            self.assertEqual(value.splitlines()[-2].strip(),
                             value_list[self.param_list.index(param)], '参数未修改成功')

        text = '-----step2:主备节点查看系统表gs_thread_memory_context中DMSMemContext字段是否存在  expect:无相关信息-----'
        self.log.info(text)

        sql1 = f"select * from {self.sys_view1} where contextname='DMSMemContext';"
        self.log.info(sql1)
        sql2 = f"select * from {self.sys_view2} where contextname='DMSMemContext';"
        self.log.info(sql2)

        for node in self.user_node:
            res1 = node.execut_db_sql(sql1)
            self.log.info(res1)
            self.assertIn('(1 row)', res1, '存在异常信息')

        text = '-----step3:主备节点查看系统表gs_session_memory_detail中DMSMemContext字段是否存在  expect:无相关信息-----'
        self.log.info(text)

        for node in self.user_node:
            res2 = node.execut_db_sql(sql2)
            self.log.info(res2)
            self.assertIn('(1 row)', res2, '存在异常信息')

            rows, _ = self.com.parse_sql_query_res(res2)
            tid1 = rows[0][0].split('.')[-1]
            self.log.info(tid1)
            sql3 = f"select * from {self.sys_view3}({tid1}, 'DMSMemContext');"
            self.log.info(sql3)
            res3 = node.execut_db_sql(sql3)
            self.log.info(res3)
            self.assertIn('ss_dms_callback.cpp', res3, '存在异常信息')

        text = '-----step4:查看enable_thread_pool参数  expect:默认值为off-----'
        self.log.info(text)
        value = self.user_node[0].execut_db_sql(f'show {self.thread_pool}')
        self.log.info(value)
        self.assertEqual(value.splitlines()[-2].strip(), 'off', '参数值异常')

        text = '-----step5:mv掉dn目录，kill掉dn进程,查看集群状态  expect:原主异常，集群内产生新主-----'
        self.log.info(text)

        pid = self.com.get_pid(self.pri_user, 'bin/gaussdb')
        self.log.info(pid)

        mv = self.pri_user.sh(f'mv {macro.DB_INSTANCE_PATH} {macro.DB_INSTANCE_PATH}_bak').result()
        self.log.info(mv)

        kill = self.pri_user.sh(f'kill -9 {pid}').result()
        self.log.info(kill)
        time.sleep(60)
        status = self.user_node[0].exec_cm_ctl('query', '-Cv')
        self.log.info(status)
        self.assertNotIn('Normal', status.splitlines()[-1].split('|')[0], '执行失败')
        self.assertTrue('Primary Normal' in status.splitlines()[-1].split('|')[1]
                        or 'Primary Normal' in status.splitlines()[-1].split('|')[-1], '集群状态异常')

        text = '-----step6:新主备节点查询相同系统视图gs_thread_memory_context中DMSMemContext字段是否存在  expect:无相关信息-----'
        self.log.info(text)

        for node in self.user_node[1:]:
            res3 = node.execut_db_sql(sql1)
            self.log.info(res3)
            self.assertIn('(1 row)', res3, '存在异常信息')

        text = '-----step7:新主备节点查询相同系统视图pgs_session_memory_detail中DMSMemContext字段是否存在  expect:无相关信息-----'
        self.log.info(text)

        for node in self.user_node[1:]:
            res4 = node.execut_db_sql(sql2)
            self.log.info(res4)
            self.assertIn('(1 row)', res4, '存在异常信息')

            rows, _ = self.com.parse_sql_query_res(res4)
            tid2 = rows[0][0].split('.')[-1]
            self.log.info(tid2)
            sql5 = f"select * from {self.sys_view3}({tid2}, 'DMSMemContext');"
            self.log.info(sql5)
            res5 = node.execut_db_sql(sql5)
            self.log.info(res5)
            self.assertIn('ss_dms_callback.cpp', res5, '存在异常信息')

    def tearDown(self):
        text = '-----step8:恢复初始环境  expect:恢复成功-----'
        self.log.info(text)

        mv_bak = self.pri_user.sh(f'mv {macro.DB_INSTANCE_PATH}_bak {macro.DB_INSTANCE_PATH};'
                                  f'ls {macro.DB_INSTANCE_PATH}').result()
        self.log.info(mv_bak)

        start = self.user_node[0].exec_cm_ctl('start')
        self.log.info(start)

        for param in self.param_list:
            reset_param = self.user_node[0].execute_gsguc('set',
                                                          self.constant.GSGUC_SUCCESS_MSG,
                                                          f'{param} = {self.default_value[self.param_list.index(param)]}')
            self.log.info(reset_param)

        restart = self.user_node[0].restart_db_cluster(False)
        self.log.info(restart)

        restore = self.user_node[0].exec_cm_ctl('switchover', '-a')
        self.log.info(restore)

        status = self.user_node[0].exec_cm_ctl('query', '-Cv')
        self.log.info(status)

        for param in self.param_list:
            reset_value = self.user_node[0].execut_db_sql(f'show {param};')
            self.log.info(reset_value)
            self.assertEqual(reset_value.splitlines()[-2].strip(),
                             self.default_value[self.param_list.index(param)], '参数恢复失败')
        self.assertIn('Primary Normal', status.splitlines()[-1].split('|')[0],
                      '恢复集群初始状态失败')
        self.log.info(f'----{os.path.basename(__file__)} end----')
